home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / cmds / tcsh / dist / sh.set.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-12-21  |  17.8 KB  |  886 lines

  1. /* $Header: /home/hyperion/mu/christos/src/sys/tcsh-6.01/RCS/sh.set.c,v 3.7 1991/12/19 22:34:14 christos Exp $ */
  2. /*
  3.  * sh.set.c: Setting and Clearing of variables
  4.  */
  5. /*-
  6.  * Copyright (c) 1980, 1991 The Regents of the University of California.
  7.  * All rights reserved.
  8.  *
  9.  * Redistribution and use in source and binary forms, with or without
  10.  * modification, are permitted provided that the following conditions
  11.  * are met:
  12.  * 1. Redistributions of source code must retain the above copyright
  13.  *    notice, this list of conditions and the following disclaimer.
  14.  * 2. Redistributions in binary form must reproduce the above copyright
  15.  *    notice, this list of conditions and the following disclaimer in the
  16.  *    documentation and/or other materials provided with the distribution.
  17.  * 3. All advertising materials mentioning features or use of this software
  18.  *    must display the following acknowledgement:
  19.  *    This product includes software developed by the University of
  20.  *    California, Berkeley and its contributors.
  21.  * 4. Neither the name of the University nor the names of its contributors
  22.  *    may be used to endorse or promote products derived from this software
  23.  *    without specific prior written permission.
  24.  *
  25.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  26.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  27.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  28.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  29.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  30.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  31.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  32.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  33.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  34.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  35.  * SUCH DAMAGE.
  36.  */
  37. #include "sh.h"
  38.  
  39. RCSID("$Id: sh.set.c,v 3.7 1991/12/19 22:34:14 christos Exp $")
  40.  
  41. #include "ed.h"
  42. #include "tw.h"
  43.  
  44. extern Char HistLit;
  45. extern bool GotTermCaps;
  46.  
  47. static    Char        *getinx        __P((Char *, int *));
  48. static    void         asx        __P((Char *, int, Char *));
  49. static    struct varent     *getvx        __P((Char *, int));
  50. static    Char        *xset        __P((Char *, Char ***));
  51. static    Char        *operate    __P((int, Char *, Char *));
  52. static    void          putn1        __P((int));
  53. static    struct varent    *madrof        __P((Char *, struct varent *));
  54. static    void         unsetv1    __P((struct varent *));
  55. static    void         exportpath    __P((Char **));
  56. static    void         balance    __P((struct varent *, int, int));
  57.  
  58. /*
  59.  * C Shell
  60.  */
  61.  
  62. /*ARGSUSED*/
  63. void
  64. doset(v, c)
  65.     register Char **v;
  66.     struct command *c;
  67. {
  68.     register Char *p;
  69.     Char   *vp, op;
  70.     Char  **vecp;
  71.     bool    hadsub;
  72.     int     subscr;
  73.  
  74.     v++;
  75.     p = *v++;
  76.     if (p == 0) {
  77.     prvars();
  78.     return;
  79.     }
  80.     do {
  81.     hadsub = 0;
  82.     vp = p;
  83.     if (letter(*p))
  84.         for (; alnum(*p); p++)
  85.         continue;
  86.     if (vp == p || !letter(*vp))
  87.         stderror(ERR_NAME | ERR_VARBEGIN);
  88.     if ((p - vp) > MAXVARLEN) {
  89.         stderror(ERR_NAME | ERR_VARTOOLONG);
  90.         return;
  91.     }
  92.     if (*p == '[') {
  93.         hadsub++;
  94.         p = getinx(p, &subscr);
  95.     }
  96.     if (op = *p) {
  97.         *p++ = 0;
  98.         if (*p == 0 && *v && **v == '(')
  99.         p = *v++;
  100.     }
  101.     else if (*v && eq(*v, STRequal)) {
  102.         op = '=', v++;
  103.         if (*v)
  104.         p = *v++;
  105.     }
  106.     if (op && op != '=')
  107.         stderror(ERR_NAME | ERR_SYNTAX);
  108.     if (eq(p, STRLparen)) {
  109.         register Char **e = v;
  110.  
  111.         if (hadsub)
  112.         stderror(ERR_NAME | ERR_SYNTAX);
  113.         for (;;) {
  114.         if (!*e)
  115.             stderror(ERR_NAME | ERR_MISSING, ')');
  116.         if (**e == ')')
  117.             break;
  118.         e++;
  119.         }
  120.         p = *e;
  121.         *e = 0;
  122.         vecp = saveblk(v);
  123.         set1(vp, vecp, &shvhed);
  124.         *e = p;
  125.         v = e + 1;
  126.     }
  127.     else if (hadsub)
  128.         asx(vp, subscr, Strsave(p));
  129.     else
  130.         set(vp, Strsave(p));
  131.     if (eq(vp, STRpath)) {
  132.         exportpath(adrof(STRpath)->vec);
  133.         dohash(NULL, NULL);
  134.     }
  135.     else if (eq(vp, STRhistchars)) {
  136.         register Char *pn = value(STRhistchars);
  137.  
  138.         HIST = *pn++;
  139.         HISTSUB = *pn;
  140.     }
  141.     else if (eq(vp, STRhistlit)) {
  142.         HistLit = 1;
  143.     }
  144.     else if (eq(vp, STRuser)) {
  145.         Setenv(STRUSER, value(vp));
  146.         Setenv(STRLOGNAME, value(vp));
  147.     }
  148.     else if (eq(vp, STRwordchars)) {
  149.         word_chars = value(vp);
  150.     }
  151.     else if (eq(vp, STRterm)) {
  152. #ifdef DOESNT_WORK_RIGHT
  153.         register Char *cp;
  154.  
  155. #endif
  156.         Setenv(STRTERM, value(vp));
  157. #ifdef DOESNT_WORK_RIGHT
  158.         cp = getenv("TERMCAP");
  159.         if (cp && (*cp != '/'))    /* if TERMCAP and not a path */
  160.         Unsetenv(STRTERMCAP);
  161. #endif                /* DOESNT_WORK_RIGHT */
  162.         GotTermCaps = 0;
  163.         ed_Init();        /* reset the editor */
  164.     }
  165.     else if (eq(vp, STRhome)) {
  166.         register Char *cp;
  167.  
  168.         cp = Strsave(value(vp));    /* get the old value back */
  169.  
  170.         /*
  171.          * convert to cononical pathname (possibly resolving symlinks)
  172.          */
  173.         cp = dcanon(cp, cp);
  174.  
  175.         set(vp, Strsave(cp));    /* have to save the new val */
  176.  
  177.         /* and now mirror home with HOME */
  178.         Setenv(STRHOME, cp);
  179.         /* fix directory stack for new tilde home */
  180.         dtilde();
  181.         xfree((ptr_t) cp);
  182.     }
  183.     else if (eq(vp, STRedit)) {
  184.         editing = 1;
  185.         /* PWP: add more stuff in here later */
  186.     }
  187.     else if (eq(vp, STRshlvl)) {
  188.         Setenv(STRSHLVL, value(vp));
  189.     }
  190.     else if (eq(vp, STRbackslash_quote)) {
  191.         bslash_quote = 1;
  192.     }
  193.     else if (eq(vp, STRrecognize_only_executables)) {
  194.         tw_clear_comm_list();
  195.     }
  196.     else if (eq(vp, STRwatch)) {
  197.         resetwatch();
  198.     }
  199.     } while (p = *v++);
  200. }
  201.  
  202. static Char *
  203. getinx(cp, ip)
  204.     register Char *cp;
  205.     register int *ip;
  206. {
  207.     *ip = 0;
  208.     *cp++ = 0;
  209.     while (*cp && Isdigit(*cp))
  210.     *ip = *ip * 10 + *cp++ - '0';
  211.     if (*cp++ != ']')
  212.     stderror(ERR_NAME | ERR_SUBSCRIPT);
  213.     return (cp);
  214. }
  215.  
  216. static void
  217. asx(vp, subscr, p)
  218.     Char   *vp;
  219.     int     subscr;
  220.     Char   *p;
  221. {
  222.     register struct varent *v = getvx(vp, subscr);
  223.  
  224.     xfree((ptr_t) v->vec[subscr - 1]);
  225.     v->vec[subscr - 1] = globone(p, G_APPEND);
  226. }
  227.  
  228. static struct varent *
  229. getvx(vp, subscr)
  230.     Char   *vp;
  231.     int     subscr;
  232. {
  233.     register struct varent *v = adrof(vp);
  234.  
  235.     if (v == 0)
  236.     udvar(vp);
  237.     if (subscr < 1 || subscr > blklen(v->vec))
  238.     stderror(ERR_NAME | ERR_RANGE);
  239.     return (v);
  240. }
  241.  
  242. /*ARGSUSED*/
  243. void
  244. dolet(v, dummy)
  245.     Char  **v;
  246.     struct command *dummy;
  247. {
  248.     register Char *p;
  249.     Char   *vp, c, op;
  250.     bool    hadsub;
  251.     int     subscr;
  252.  
  253.     v++;
  254.     p = *v++;
  255.     if (p == 0) {
  256.     prvars();
  257.     return;
  258.     }
  259.     do {
  260.     hadsub = 0;
  261.     vp = p;
  262.     if (letter(*p))
  263.         for (; alnum(*p); p++)
  264.         continue;
  265.     if (vp == p || !letter(*vp))
  266.         stderror(ERR_NAME | ERR_VARBEGIN);
  267.     if ((p - vp) > MAXVARLEN)
  268.         stderror(ERR_NAME | ERR_VARTOOLONG);
  269.     if (*p == '[') {
  270.         hadsub++;
  271.         p = getinx(p, &subscr);
  272.     }
  273.     if (*p == 0 && *v)
  274.         p = *v++;
  275.     if (op = *p)
  276.         *p++ = 0;
  277.     else
  278.         stderror(ERR_NAME | ERR_ASSIGN);
  279.  
  280.     /*
  281.      * if there is no expression after the '=' then print a "Syntax Error"
  282.      * message - strike
  283.      */
  284.     if (*p == '\0' && *v == NULL)
  285.         stderror(ERR_NAME | ERR_ASSIGN);
  286.  
  287.     vp = Strsave(vp);
  288.     if (op == '=') {
  289.         c = '=';
  290.         p = xset(p, &v);
  291.     }
  292.     else {
  293.         c = *p++;
  294.         if (any("+-", c)) {
  295.         if (c != op || *p)
  296.             stderror(ERR_NAME | ERR_UNKNOWNOP);
  297.         p = Strsave(STR1);
  298.         }
  299.         else {
  300.         if (any("<>", op)) {
  301.             if (c != op)
  302.             stderror(ERR_NAME | ERR_UNKNOWNOP);
  303.             c = *p++;
  304.             stderror(ERR_NAME | ERR_SYNTAX);
  305.         }
  306.         if (c != '=')
  307.             stderror(ERR_NAME | ERR_UNKNOWNOP);
  308.         p = xset(p, &v);
  309.         }
  310.     }
  311.     if (op == '=')
  312.         if (hadsub)
  313.         asx(vp, subscr, p);
  314.         else
  315.         set(vp, p);
  316.     else if (hadsub) {
  317.         struct varent *gv = getvx(vp, subscr);
  318.  
  319.         asx(vp, subscr, operate(op, gv->vec[subscr - 1], p));
  320.     }
  321.     else
  322.         set(vp, operate(op, value(vp), p));
  323.     if (eq(vp, STRpath)) {
  324.         exportpath(adrof(STRpath)->vec);
  325.         dohash(NULL, NULL);
  326.     }
  327.     xfree((ptr_t) vp);
  328.     if (c != '=')
  329.         xfree((ptr_t) p);
  330.     } while (p = *v++);
  331. }
  332.  
  333. static Char *
  334. xset(cp, vp)
  335.     Char   *cp, ***vp;
  336. {
  337.     register Char *dp;
  338.  
  339.     if (*cp) {
  340.     dp = Strsave(cp);
  341.     --(*vp);
  342.     xfree((ptr_t) ** vp);
  343.     **vp = dp;
  344.     }
  345.     return (putn(expr(vp)));
  346. }
  347.  
  348. static Char *
  349. operate(op, vp, p)
  350.     int     op;
  351.     Char    *vp, *p;
  352. {
  353.     Char    opr[2];
  354.     Char   *vec[5];
  355.     register Char **v = vec;
  356.     Char  **vecp = v;
  357.     register int i;
  358.  
  359.     if (op != '=') {
  360.     if (*vp)
  361.         *v++ = vp;
  362.     opr[0] = op;
  363.     opr[1] = 0;
  364.     *v++ = opr;
  365.     if (op == '<' || op == '>')
  366.         *v++ = opr;
  367.     }
  368.     *v++ = p;
  369.     *v++ = 0;
  370.     i = expr(&vecp);
  371.     if (*vecp)
  372.     stderror(ERR_NAME | ERR_EXPRESSION);
  373.     return (putn(i));
  374. }
  375.  
  376. static Char *putp, nbuf[50];
  377.  
  378. Char   *
  379. putn(n)
  380.     register int n;
  381. {
  382.     int     num;
  383.  
  384.     putp = nbuf;
  385.     if (n < 0) {
  386.     n = -n;
  387.     *putp++ = '-';
  388.     }
  389.     num = 2;            /* confuse lint */
  390.     if (sizeof(int) == num && ((unsigned int) n) == 32768) {
  391.     *putp++ = '3';
  392.     n = 2768;
  393. #ifdef pdp11
  394.     }
  395. #else
  396.     }
  397.     else {
  398.     num = 4;        /* confuse lint */
  399.     if (sizeof(int) == num && ((unsigned int) n) == 2147483648) {
  400.         *putp++ = '2';
  401.         n = 147483648;
  402.     }
  403.     }
  404. #endif
  405.     putn1(n);
  406.     *putp = 0;
  407.     return (Strsave(nbuf));
  408. }
  409.  
  410. static void
  411. putn1(n)
  412.     register int n;
  413. {
  414.     if (n > 9)
  415.     putn1(n / 10);
  416.     *putp++ = n % 10 + '0';
  417. }
  418.  
  419. int
  420. getn(cp)
  421.     register Char *cp;
  422. {
  423.     register int n;
  424.     int     sign;
  425.  
  426.     if (!cp)            /* PWP: extra error checking */
  427.     stderror(ERR_NAME | ERR_BADNUM);
  428.  
  429.     sign = 0;
  430.     if (cp[0] == '+' && cp[1])
  431.     cp++;
  432.     if (*cp == '-') {
  433.     sign++;
  434.     cp++;
  435.     if (!Isdigit(*cp))
  436.         stderror(ERR_NAME | ERR_BADNUM);
  437.     }
  438.     n = 0;
  439.     while (Isdigit(*cp))
  440.     n = n * 10 + *cp++ - '0';
  441.     if (*cp)
  442.     stderror(ERR_NAME | ERR_BADNUM);
  443.     return (sign ? -n : n);
  444. }
  445.  
  446. Char   *
  447. value1(var, head)
  448.     Char   *var;
  449.     struct varent *head;
  450. {
  451.     register struct varent *vp;
  452.  
  453.     if (!var || !head)        /* PWP: extra error checking */
  454.     return (STRNULL);
  455.  
  456.     vp = adrof1(var, head);
  457.     return (vp == 0 || vp->vec[0] == 0 ? STRNULL : vp->vec[0]);
  458. }
  459.  
  460. static struct varent *
  461. madrof(pat, vp)
  462.     Char   *pat;
  463.     register struct varent *vp;
  464. {
  465.     register struct varent *vp1;
  466.  
  467.     for (; vp; vp = vp->v_right) {
  468.     if (vp->v_left && (vp1 = madrof(pat, vp->v_left)))
  469.         return vp1;
  470.     if (Gmatch(vp->v_name, pat))
  471.         return vp;
  472.     }
  473.     return vp;
  474. }
  475.  
  476. struct varent *
  477. adrof1(name, v)
  478.     register Char *name;
  479.     register struct varent *v;
  480. {
  481.     register cmp;
  482.  
  483.     v = v->v_left;
  484.     while (v && ((cmp = *name - *v->v_name) || (cmp = Strcmp(name, v->v_name))))
  485.     if (cmp < 0)
  486.         v = v->v_left;
  487.     else
  488.         v = v->v_right;
  489.     return v;
  490. }
  491.  
  492. /*
  493.  * The caller is responsible for putting value in a safe place
  494.  */
  495. void
  496. set(var, val)
  497.     Char   *var, *val;
  498. {
  499.     register Char **vec = (Char **) xmalloc((size_t) (2 * sizeof(Char **)));
  500.  
  501.     vec[0] = val;
  502.     vec[1] = 0;
  503.     set1(var, vec, &shvhed);
  504. }
  505.  
  506. void
  507. set1(var, vec, head)
  508.     Char   *var, **vec;
  509.     struct varent *head;
  510. {
  511.     register Char **oldv = vec;
  512.  
  513.     gflag = 0;
  514.     tglob(oldv);
  515.     if (gflag) {
  516.     vec = globall(oldv);
  517.     if (vec == 0) {
  518.         blkfree(oldv);
  519.         stderror(ERR_NAME | ERR_NOMATCH);
  520.         return;
  521.     }
  522.     blkfree(oldv);
  523.     gargv = 0;
  524.     }
  525.     setq(var, vec, head);
  526. }
  527.  
  528.  
  529. void
  530. setq(name, vec, p)
  531.     Char   *name, **vec;
  532.     register struct varent *p;
  533. {
  534.     register struct varent *c;
  535.     register f;
  536.  
  537.     f = 0;            /* tree hangs off the header's left link */
  538.     while (c = p->v_link[f]) {
  539.     if ((f = *name - *c->v_name) == 0 &&
  540.         (f = Strcmp(name, c->v_name)) == 0) {
  541.         blkfree(c->vec);
  542.         goto found;
  543.     }
  544.     p = c;
  545.     f = f > 0;
  546.     }
  547.     p->v_link[f] = c = (struct varent *) xmalloc((size_t)sizeof(struct varent));
  548.     c->v_name = Strsave(name);
  549.     c->v_bal = 0;
  550.     c->v_left = c->v_right = 0;
  551.     c->v_parent = p;
  552.     balance(p, f, 0);
  553. found:
  554.     trim(c->vec = vec);
  555. }
  556.  
  557. /*ARGSUSED*/
  558. void
  559. unset(v, c)
  560.     Char   **v;
  561.     struct command *c;
  562. {
  563.     register bool did_only;
  564.  
  565.     did_only = adrof(STRrecognize_only_executables) != 0;
  566.     unset1(v, &shvhed);
  567.     if (adrof(STRhistchars) == 0) {
  568.     HIST = '!';
  569.     HISTSUB = '^';
  570.     }
  571.     if (adrof(STRhistlit) == 0)
  572.     HistLit = 0;
  573.     if (adrof(STRwordchars) == 0)
  574.     word_chars = STR_WORD_CHARS;
  575.     if (adrof(STRedit) == 0)
  576.     editing = 0;
  577.     if (adrof(STRbackslash_quote) == 0)
  578.     bslash_quote = 0;
  579.     if (did_only && adrof(STRrecognize_only_executables) == 0)
  580.     tw_clear_comm_list();
  581. }
  582.  
  583. void
  584. unset1(v, head)
  585.     register Char *v[];
  586.     struct varent *head;
  587. {
  588.     register struct varent *vp;
  589.     register int cnt;
  590.  
  591.     while (*++v) {
  592.     cnt = 0;
  593.     while (vp = madrof(*v, head->v_left))
  594.         unsetv1(vp), cnt++;
  595.     if (cnt == 0)
  596.         setname(short2str(*v));
  597.     }
  598. }
  599.  
  600. void
  601. unsetv(var)
  602.     Char   *var;
  603. {
  604.     register struct varent *vp;
  605.  
  606.     if ((vp = adrof1(var, &shvhed)) == 0)
  607.     udvar(var);
  608.     unsetv1(vp);
  609. }
  610.  
  611. static void
  612. unsetv1(p)
  613.     register struct varent *p;
  614. {
  615.     register struct varent *c, *pp;
  616.     register f;
  617.  
  618.     /*
  619.      * Free associated memory first to avoid complications.
  620.      */
  621.     blkfree(p->vec);
  622.     xfree((ptr_t) p->v_name);
  623.     /*
  624.      * If p is missing one child, then we can move the other into where p is.
  625.      * Otherwise, we find the predecessor of p, which is guaranteed to have no
  626.      * right child, copy it into p, and move it's left child into it.
  627.      */
  628.     if (p->v_right == 0)
  629.     c = p->v_left;
  630.     else if (p->v_left == 0)
  631.     c = p->v_right;
  632.     else {
  633.     for (c = p->v_left; c->v_right; c = c->v_right);
  634.     p->v_name = c->v_name;
  635.     p->vec = c->vec;
  636.     p = c;
  637.     c = p->v_left;
  638.     }
  639.     /*
  640.      * Move c into where p is.
  641.      */
  642.     pp = p->v_parent;
  643.     f = pp->v_right == p;
  644.     if (pp->v_link[f] = c)
  645.     c->v_parent = pp;
  646.     /*
  647.      * Free the deleted node, and rebalance.
  648.      */
  649.     xfree((ptr_t) p);
  650.     balance(pp, f, 1);
  651. }
  652.  
  653. void
  654. setNS(cp)
  655.     Char   *cp;
  656. {
  657.     set(cp, Strsave(STRNULL));
  658. }
  659.  
  660. /*ARGSUSED*/
  661. void
  662. shift(v, c)
  663.     register Char **v;
  664.     struct command *c;
  665. {
  666.     register struct varent *argv;
  667.     register Char *name;
  668.  
  669.     v++;
  670.     name = *v;
  671.     if (name == 0)
  672.     name = STRargv;
  673.     else
  674.     (void) strip(name);
  675.     argv = adrof(name);
  676.     if (argv == 0)
  677.     udvar(name);
  678.     if (argv->vec[0] == 0)
  679.     stderror(ERR_NAME | ERR_NOMORE);
  680.     lshift(argv->vec, 1);
  681. }
  682.  
  683. static void
  684. exportpath(val)
  685.     Char  **val;
  686. {
  687.     Char    exppath[BUFSIZE];
  688.  
  689.     exppath[0] = 0;
  690.     if (val)
  691.     while (*val) {
  692.         if (Strlen(*val) + Strlen(exppath) + 2 > BUFSIZE) {
  693.         xprintf("Warning: ridiculously long PATH truncated\n");
  694.         break;
  695.         }
  696.         (void) Strcat(exppath, *val++);
  697.         if (*val == 0 || eq(*val, STRRparen))
  698.         break;
  699.         (void) Strcat(exppath, STRcolon);
  700.     }
  701.     Setenv(STRPATH, exppath);
  702. }
  703.  
  704. #ifndef lint
  705.  /*
  706.   * Lint thinks these have null effect
  707.   */
  708.  /* macros to do single rotations on node p */
  709. #define rright(p) (\
  710.     t = (p)->v_left,\
  711.     (t)->v_parent = (p)->v_parent,\
  712.     ((p)->v_left = t->v_right) ? (t->v_right->v_parent = (p)) : 0,\
  713.     (t->v_right = (p))->v_parent = t,\
  714.     (p) = t)
  715. #define rleft(p) (\
  716.     t = (p)->v_right,\
  717.     (t)->v_parent = (p)->v_parent,\
  718.     ((p)->v_right = t->v_left) ? (t->v_left->v_parent = (p)) : 0,\
  719.     (t->v_left = (p))->v_parent = t,\
  720.     (p) = t)
  721. #else
  722. struct varent *
  723. rleft(p)
  724.     struct varent *p;
  725. {
  726.     return (p);
  727. }
  728. struct varent *
  729. rright(p)
  730.     struct varent *p;
  731. {
  732.     return (p);
  733. }
  734.  
  735. #endif                /* ! lint */
  736.  
  737.  
  738. /*
  739.  * Rebalance a tree, starting at p and up.
  740.  * F == 0 means we've come from p's left child.
  741.  * D == 1 means we've just done a delete, otherwise an insert.
  742.  */
  743. static void
  744. balance(p, f, d)
  745.     register struct varent *p;
  746.     register int f, d;
  747. {
  748.     register struct varent *pp;
  749.  
  750. #ifndef lint
  751.     register struct varent *t;    /* used by the rotate macros */
  752.  
  753. #endif
  754.     register ff;
  755.  
  756.     /*
  757.      * Ok, from here on, p is the node we're operating on; pp is it's parent; f
  758.      * is the branch of p from which we have come; ff is the branch of pp which
  759.      * is p.
  760.      */
  761.     for (; pp = p->v_parent; p = pp, f = ff) {
  762.     ff = pp->v_right == p;
  763.     if (f ^ d) {        /* right heavy */
  764.         switch (p->v_bal) {
  765.         case -1:        /* was left heavy */
  766.         p->v_bal = 0;
  767.         break;
  768.         case 0:        /* was balanced */
  769.         p->v_bal = 1;
  770.         break;
  771.         case 1:        /* was already right heavy */
  772.         switch (p->v_right->v_bal) {
  773.         case 1:    /* sigle rotate */
  774.             pp->v_link[ff] = rleft(p);
  775.             p->v_left->v_bal = 0;
  776.             p->v_bal = 0;
  777.             break;
  778.         case 0:    /* single rotate */
  779.             pp->v_link[ff] = rleft(p);
  780.             p->v_left->v_bal = 1;
  781.             p->v_bal = -1;
  782.             break;
  783.         case -1:    /* double rotate */
  784.             (void) rright(p->v_right);
  785.             pp->v_link[ff] = rleft(p);
  786.             p->v_left->v_bal =
  787.             p->v_bal < 1 ? 0 : -1;
  788.             p->v_right->v_bal =
  789.             p->v_bal > -1 ? 0 : 1;
  790.             p->v_bal = 0;
  791.             break;
  792.         default:
  793.             break;
  794.         }
  795.         break;
  796.         default:
  797.         break;
  798.         }
  799.     }
  800.     else {            /* left heavy */
  801.         switch (p->v_bal) {
  802.         case 1:        /* was right heavy */
  803.         p->v_bal = 0;
  804.         break;
  805.         case 0:        /* was balanced */
  806.         p->v_bal = -1;
  807.         break;
  808.         case -1:        /* was already left heavy */
  809.         switch (p->v_left->v_bal) {
  810.         case -1:    /* single rotate */
  811.             pp->v_link[ff] = rright(p);
  812.             p->v_right->v_bal = 0;
  813.             p->v_bal = 0;
  814.             break;
  815.         case 0:    /* signle rotate */
  816.             pp->v_link[ff] = rright(p);
  817.             p->v_right->v_bal = -1;
  818.             p->v_bal = 1;
  819.             break;
  820.         case 1:    /* double rotate */
  821.             (void) rleft(p->v_left);
  822.             pp->v_link[ff] = rright(p);
  823.             p->v_left->v_bal =
  824.             p->v_bal < 1 ? 0 : -1;
  825.             p->v_right->v_bal =
  826.             p->v_bal > -1 ? 0 : 1;
  827.             p->v_bal = 0;
  828.             break;
  829.         default:
  830.             break;
  831.         }
  832.         break;
  833.         default:
  834.         break;
  835.         }
  836.     }
  837.     /*
  838.      * If from insert, then we terminate when p is balanced. If from
  839.      * delete, then we terminate when p is unbalanced.
  840.      */
  841.     if ((p->v_bal == 0) ^ d)
  842.         break;
  843.     }
  844. }
  845.  
  846. void
  847. plist(p)
  848.     register struct varent *p;
  849. {
  850.     register struct varent *c;
  851.     register len;
  852.  
  853.     if (setintr)
  854. #ifdef BSDSIGS
  855.     (void) sigsetmask(sigblock((sigmask_t) 0) & ~sigmask(SIGINT));
  856. #else                /* BSDSIGS */
  857.     (void) sigrelse(SIGINT);
  858. #endif                /* BSDSIGS */
  859.  
  860.     for (;;) {
  861.     while (p->v_left)
  862.         p = p->v_left;
  863. x:
  864.     if (p->v_parent == 0)    /* is it the header? */
  865.         return;
  866.     len = blklen(p->vec);
  867.     xprintf(short2str(p->v_name));
  868.     xputchar('\t');
  869.     if (len != 1)
  870.         xputchar('(');
  871.     blkpr(p->vec);
  872.     if (len != 1)
  873.         xputchar(')');
  874.     xputchar('\n');
  875.     if (p->v_right) {
  876.         p = p->v_right;
  877.         continue;
  878.     }
  879.     do {
  880.         c = p;
  881.         p = p->v_parent;
  882.     } while (p->v_right == c);
  883.     goto x;
  884.     }
  885. }
  886.